//
//  NSObject+Category.m
//  Objective-C
//
//  Created by S_Line on 2018/11/8.
//  Copyright © 2018 S_Line. All rights reserved.
//

#import "NSObject+SLCategory.h"

#import <objc/runtime.h>

@implementation NSObject (SLCategory)

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
//        Method m1 = class_getInstanceMethod(self, @selector(description));
//        Method m2 = class_getInstanceMethod(self, @selector(sl_description));
//
//        method_exchangeImplementations(m1, m2);
    });
}

- (NSString *)sl_description {
    NSString *str = [self sl_description];
    
    Class class = [self class];
    NSMutableDictionary *ivarDict = [NSMutableDictionary new];
    do {
        unsigned int count = 0;
        Ivar *ivarList = class_copyIvarList(class, &count);
        for (int i = 0; i < count; i++) {
            Ivar ivar = ivarList[i];
            const char *ivarNameChar = ivar_getName(ivar);
            NSString *ivarName = [NSString stringWithUTF8String:ivarNameChar];
            NSString *key = [ivarName substringFromIndex:1];
            NSValue *value = [self valueForKey:key];
            
            NSString *ivarTypeStr = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
            ivarTypeStr = [ivarTypeStr stringByReplacingOccurrencesOfString:@"\"" withString:@""];
            ivarTypeStr = [ivarTypeStr stringByReplacingOccurrencesOfString:@"@" withString:@""];
            
            if (value) {
                [ivarDict setObject:value forKey:key];
            } else {
                [ivarDict setObject:@"nil" forKey:key];
            }
        }
        
        class = [class superclass];
        
        free(ivarList);
        
    } while (![NSStringFromClass(class) isEqualToString:NSStringFromClass([NSObject class])]);
    
    
    return [NSString stringWithFormat:@"\n%@\n%@\n", str, ivarDict];
}


/**
 创建KeyedArchiverCode
 */
+ (void)createKeyedArchiverCode {
    NSMutableString *codeStr = [NSMutableString string];
    unsigned int count;
    Ivar *ivarList = class_copyIvarList(self, &count);
    
    [codeStr appendFormat:@"%@", @"\n- (instancetype)initWithCoder:(NSCoder *)aDecoder {\n"];
    [codeStr appendFormat:@"%@", @"    if ([super init]) {\n"];
    
    for (int i = 0; i < count; i++) {
        Ivar ivar = ivarList[i];
        
        NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)];
        NSString *key = [ivarName substringFromIndex:1];
        [codeStr appendFormat:@"        self.%@ = [aDecoder decodeObjectForKey:@\"%@\"];\n", key, key];
    }
    
    [codeStr appendFormat:@"    }\n"];
    [codeStr appendFormat:@"    return self;\n"];
    [codeStr appendFormat:@"}\n\n\n"];
    
    [codeStr appendFormat:@"- (void)encodeWithCoder:(NSCoder *)aCoder {\n"];
    
    for (int i = 0; i < count; i++) {
        Ivar ivar = ivarList[i];
        
        NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)];
        NSString *key = [ivarName substringFromIndex:1];
        [codeStr appendFormat:@"    [aCoder encodeObject:self.%@ forKey:@\"%@\"];\n", key, key];
    }
    [codeStr appendFormat:@"}\n"];
    
    NSLog(@"%@", codeStr);
}

@end
